#include "util_time_format.h"
#include "util_netstream.h"
#include <time.h>
#ifdef WINDOWS_IMPL
#include <windows.h>
#else
#include <sys/time.h>>
#endif

namespace util {
DateTime DateTime::currentTime()
{
	DateTime ret;
#if defined(WINDOWS_IMPL)
	SYSTEMTIME sys;
	GetLocalTime(&sys);
	ret.year = sys.wYear;
	ret.month = sys.wMonth;
	ret.day = sys.wDay;
	ret.hour = sys.wHour;
	ret.minute = sys.wMinute;
	ret.second = sys.wSecond;
	ret.milisecond = sys.wMilliseconds;
#else
	struct timeval    tv;
	struct timezone   tz;
	struct tm         tm;
	gettimeofday(&tv, &tz);
	localtime_r(&tv.tv_sec, &tm);
	ret.year = tm.tm_year + 900;
	ret.month = tm.tm_mon;
	ret.day = tm.tm_mday;
	ret.hour = tm.tm_hour;
	ret.minute = tm.tm_min;
	ret.second = tm.tm_sec;
	ret.milisecond = tv.tv_usec/1000;
#endif
	return ret;
}

std::string DateTime::format(const char * fmt)
{
	char tmp[10];
	CNetStreamMaker nsm;
	for (int i = 0; fmt[i]; i++) {
		if (fmt[i] == '%') {
			if (fmt[i + 1] == 'y') {
				sprintf(tmp, "%02d", year % 100);
			}
			else if (fmt[i + 1] == 'Y') {
				sprintf(tmp, "%04d", year);
			}
			else if (fmt[i + 1] == 'm') {
				sprintf(tmp, "%02d", month);
			}
			else if (fmt[i + 1] == 'd') {
				sprintf(tmp, "%02d", day);
			}
			else if (fmt[i + 1] == 'H') {
				sprintf(tmp, "%02d", hour);
			}
			else if (fmt[i + 1] == 'I') {
				sprintf(tmp, "%02d", hour % 12);
			}
			else if (fmt[i + 1] == 'M') {
				sprintf(tmp, "%02d", minute);
			}
			else if (fmt[i + 1] == 'S') {
				sprintf(tmp, "%02d", second);
			}
			else if (fmt[i + 1] == 'X') {
				sprintf(tmp, "%03d", milisecond);
			}
			else {
				sprintf(tmp, "%c", fmt[i + 1]);
			}
			i++;
			nsm.append_string(tmp);
		}
		else {
			nsm.append_byte(fmt[i]);
		}
	}

	return nsm.get();
}

time_t CTimeFormat::scanTime(const char buf[32])
{
    struct tm tm;
    sscanf(buf, "%4d%2d%2d%2d%2d%2d",
        &tm.tm_year,
        &tm.tm_mon,
        &tm.tm_mday,
        &tm.tm_hour,
        &tm.tm_min,
        &tm.tm_sec);

    tm.tm_year -= 1900;
    tm.tm_mon--;
    tm.tm_isdst = -1;

    return mktime(&tm);
}

char *CTimeFormat::printNow(const char *fmt, char buf[32])
{
    time_t now = time(NULL);
    struct tm tm;
#if defined(WINDOWS_IMPL)
    localtime_s(&tm, &now);
#elif defined(LINUX_IMPL)
    localtime_r(&now, &tm);
#endif

    strftime(buf, 32, fmt, &tm);
    return buf;
}

std::string CTimeFormat::printNow(const char *fmt) {
    time_t now = time(NULL);
    struct tm tm;
#if defined(WINDOWS_IMPL)
    localtime_s(&tm, &now);
#elif defined(LINUX_IMPL)
    localtime_r(&now, &tm);
#endif

    char buf[32];
    strftime(buf, 32, fmt, &tm);
    return buf;
}

char *CTimeFormat::printTime(time_t time, const char *fmt, char buf[32])
{
    struct tm tm;
#if defined(WINDOWS_IMPL)
    localtime_s(&tm, &time);
#elif defined(LINUX_IMPL)
    localtime_r(&time, &tm);
#endif

    strftime(buf, 32, fmt, &tm);
    return buf;
}

std::string CTimeFormat::printTime(time_t time, const char *fmt) {
    struct tm tm;
#if defined(WINDOWS_IMPL)
    localtime_s(&tm, &time);
#elif defined(LINUX_IMPL)
    localtime_r(&time, &tm);
#endif

    char buf[32];
    strftime(buf, 32, fmt, &tm);
    return buf;
}

struct tm CTimeFormat::getTimeInfo(time_t time) {
    struct tm tm;
#if defined(WINDOWS_IMPL)
    localtime_s(&tm, &time);
#elif defined(LINUX_IMPL)
    localtime_r(&time, &tm);
#endif
    return tm;
}
}